"#include \"AtmosphereShadersCommon.fxh\"\n"
"\n"
"cbuffer cbParticipatingMediaScatteringParams\n"
"{\n"
"    AirScatteringAttribs g_MediaParams;\n"
"}\n"
"\n"
"Texture2D<float2> g_tex2DOccludedNetDensityToAtmTop;\n"
"SamplerState g_tex2DOccludedNetDensityToAtmTop_sampler;\n"
"\n"
"#include \"LookUpTables.fxh\"\n"
"#include \"PrecomputeCommon.fxh\"\n"
"#include \"ScatteringIntegrals.fxh\"\n"
"\n"
"Texture3D<float3> g_tex3DPreviousSctrOrder;\n"
"SamplerState g_tex3DPreviousSctrOrder_sampler;\n"
"\n"
"Texture2D<float3> g_tex2DSphereRandomSampling;\n"
"\n"
"RWTexture3D</*format = rgba32f*/float3> g_rwtex3DSctrRadiance;\n"
"\n"
"// This shader pre-computes the radiance of light scattered at a given point in given\n"
"// direction. It multiplies the previous order in-scattered light with the phase function \n"
"// for each type of particles and integrates the result over the whole set of directions,\n"
"// see eq. (7) in [Bruneton and Neyret 08].\n"
"[numthreads(THREAD_GROUP_SIZE, THREAD_GROUP_SIZE, 1)]\n"
"void ComputeSctrRadianceCS(uint3 ThreadId  : SV_DispatchThreadID)\n"
"{\n"
"    // Get attributes for the current point\n"
"    float4 f4LUTCoords = LUTCoordsFromThreadID(ThreadId);\n"
"    float fAltitude, fCosViewZenithAngle, fCosSunZenithAngle, fCosSunViewAngle;\n"
"    InsctrLUTCoords2WorldParams(f4LUTCoords,\n"
"                                g_MediaParams.fEarthRadius,\n"
"                                g_MediaParams.fAtmBottomAltitude,\n"
"                                g_MediaParams.fAtmTopAltitude,\n"
"                                fAltitude,\n"
"                                fCosViewZenithAngle,\n"
"                                fCosSunZenithAngle,\n"
"                                fCosSunViewAngle );\n"
"    float3 f3EarthCentre = float3(0.0, -g_MediaParams.fEarthRadius, 0.0);\n"
"    float3 f3RayStart    = float3(0.0, fAltitude, 0.0);\n"
"    float3 f3ViewDir     = ComputeViewDir(fCosViewZenithAngle);\n"
"    float3 f3DirOnLight  = ComputeLightDir(f3ViewDir, fCosSunZenithAngle, fCosSunViewAngle);\n"
"    \n"
"    // Compute particle density scale factor\n"
"    float2 f2ParticleDensity = exp( -float2(fAltitude, fAltitude) * g_MediaParams.f4ParticleScaleHeight.zw );\n"
"    \n"
"    float3 f3SctrRadiance = float3(0.0, 0.0, 0.0);\n"
"    // Go through a number of samples randomly distributed over the sphere\n"
"    for(int iSample = 0; iSample < NUM_RANDOM_SPHERE_SAMPLES; ++iSample)\n"
"    {\n"
"        // Get random direction\n"
"        float3 f3RandomDir = normalize( g_tex2DSphereRandomSampling.Load(int3(iSample,0,0)) );\n"
"        // Get the previous order in-scattered light when looking in direction f3RandomDir (the light thus goes in direction -f3RandomDir)\n"
"        float4 f4UVWQ = float4(-1.0, -1.0, -1.0, -1.0);\n"
"        float3 f3PrevOrderSctr = LookUpPrecomputedScattering(\n"
"            f3RayStart,\n"
"            f3RandomDir,\n"
"            f3EarthCentre,\n"
"            g_MediaParams.fEarthRadius,\n"
"            f3DirOnLight.xyz,\n"
"            g_MediaParams.fAtmBottomAltitude,\n"
"            g_MediaParams.fAtmTopAltitude,\n"
"            g_tex3DPreviousSctrOrder,\n"
"            g_tex3DPreviousSctrOrder_sampler,\n"
"            f4UVWQ); \n"
"        \n"
"        // Apply phase functions for each type of particles\n"
"        // Note that total scattering coefficients are baked into the angular scattering coeffs\n"
"        float3 f3DRlghInsctr = f2ParticleDensity.x * f3PrevOrderSctr;\n"
"        float3 f3DMieInsctr  = f2ParticleDensity.y * f3PrevOrderSctr;\n"
"        float fCosTheta = dot(f3ViewDir, f3RandomDir);\n"
"        ApplyPhaseFunctions(f3DRlghInsctr, f3DMieInsctr, fCosTheta);\n"
"\n"
"        f3SctrRadiance += f3DRlghInsctr + f3DMieInsctr;\n"
"    }\n"
"    // Since we tested N random samples, each sample covered 4*Pi / N solid angle\n"
"    // Note that our phase function is normalized to 1 over the sphere. For instance,\n"
"    // uniform phase function would be p(theta) = 1 / (4*Pi).\n"
"    // Notice that for uniform intensity I if we get N samples, we must obtain exactly I after\n"
"    // numeric integration\n"
"    f3SctrRadiance *= 4.0*PI / float(NUM_RANDOM_SPHERE_SAMPLES);\n"
"\n"
"    g_rwtex3DSctrRadiance[ThreadId] = f3SctrRadiance;\n"
"}\n"
"\n"
